注意:所有文章除特别说明外,转载请注明出处.
简介
该模式允许向一个现有的对象添加新的功能,同时不改变其结构。此模式创建了一个装饰类,用来包装原有的类,并在保持方法签名完整性的前提下,提供额外的功能。装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
场景
1. 扩展一个类的功能或给一个类添加附加职责
2. 动态的给一个对象添加功能,这些功能可以动态的撤销
优点
1. 继承的有力补充,比继承灵活,不改变原有对象的情况下给一个对象扩展功能
2. 通过使用不同类型以及这些装饰类的排列组合可以实现不同的效果
3. 符合开闭原则
缺点
1. 会出现更多的代码,更多的类,增加程序的复杂性
2. 动态装饰或多层装饰时会更加复杂
相关设计模式
1. 装饰者模式与代理模式
2. 适配器模式
装饰器模式具体实现
1.创建接口
public interface Shape {
void draw();
}
2.创建实现接口的实现类
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Rectangle");
}
}
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Circle");
}
}
3.创建实现Shape接口的抽象装饰类
public abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;
public ShapeDecorator(Shape decoratedShape){
this.decoratedShape = decoratedShape;
}
public void draw(){
decoratedShape.draw();
}
}
4.创建扩展了ShapeDecorator类的实体装饰类
public class RedShapeDecorator extends ShapeDecorator {
public RedShapeDecorator(Shape decoratedShape) {
super(decoratedShape);
}
@Override
public void draw() {
decoratedShape.draw();
setRedBorder(decoratedShape);
}
private void setRedBorder(Shape decoratedShape){
System.out.println("Border Color: Red");
}
}
5.使用 RedShapeDecorator 来装饰 Shape 对象
public class DecoratorPatternDemo {
public static void main(String[] args) {
Shape circle = new Circle();
Shape redCircle = new RedShapeDecorator(new Circle());
Shape redRectangle = new RedShapeDecorator(new Rectangle());
System.out.println("Circle with normal border");
circle.draw();
System.out.println("\nCircle of red border");
redCircle.draw();
System.out.println("\nRectangle of red border");
redRectangle.draw();
}
}
总结
装饰者模式表示在已有的类的基础上动态的添加额外的功能。装饰者模式和Spring中的AOP功能类似,在原有的程序的基础上通过横切代码补充原先没有的功能。
Java IO 的装饰者模式
InputStream
/|\
ByteArrayInputStream FileInpuStream PipedInputStream FilterInputStream extends InputStream
提示:这里的InputStream代表了输入流,具体的输入来源可以是文件(FileInputStream)、管道(PipedInputStream)、数组(ByteArrayInputStream)等。FilterInputStream承接了装饰模式的关键节点,其实现类是一系列装饰器,比如 BufferedInputStream 代表用缓冲来装饰,也就使得输入流具有了缓冲的功能,LineNumberInputStream 代表用行号来装饰,在操作的时候就可以取得行号了,DataInputStream 的装饰,使得我们可以从输入流转换为 java 中的基本类型值。